// 每条蛇
import { AcGameObject } from "./AcGameObject";
import { Cell } from "./Cell";

export class Snake extends AcGameObject {
    constructor(info, gamemap) {
        super();

        this.id = info.id;
        this.color = info.color;
        this.gamemap = gamemap;
        
        this.next_cell = null; // 蛇在下一步要前往的目的地
        this.cells = [new Cell(info.r, info.c)]; // 存放蛇的身体，初始时蛇只有一格

        this.speed = 5; // 蛇的速度，每秒走5个各自

        this.direction = -1; // -1表示没有指令， 0，1，2，3表示上右下左
        this.status = "idle"; // idle表示静止，move表示正在移动, die表示已死亡

        this.dr = [-1, 0, 1, 0]; // 蛇行方向便宜了
        this.dc = [0, 1, 0, -1]; // 蛇列方向偏移量

        this.step = 0; // 当前蛇走了几步

        this.eps = 1e-2; // 当两个点距离在eps内以后，则说明他们在同一个地方

        this.eye_direction = 0; // 眼睛的方向
        if (this.id === 1) {
            this.eye_direction = 2; // 左下角的初始朝上
        }

        this.eye_dx = [ // 蛇眼睛不同方向的偏移量, 左眼和右眼
            [-1, 1],
            [1, 1],
            [1, -1],
            [-1, -1],
        ];

        this.eye_dy = [
            [-1, -1],
            [-1, 1],
            [1, 1],
            [-1, 1],
        ]
    }

    next_step() { // 将蛇的状态变为走下一步
        const d = this.direction;
        this.next_cell = new Cell(this.cells[0].r + this.dr[d], this.cells[0].c + this.dc[d]); // 走下一步
        this.direction = -1; // 清空操作
        this.eye_direction = d;
        this.status = "move";
        this.step ++ ;

        const len = this.cells.length;
        for (let i = len; i > 0; i -- ) {
            this.cells[i] = JSON.parse(JSON.stringify(this.cells[i - 1]));
        }

        if (!this.gamemap.check_valid(this.next_cell)) { // 若下一步操作撞了
            this.status = "die";
        }
    }

    start() {

    }

    set_direction(d) {
        this.direction = d;
    }

    update_move() { 
        const move_distance = this.speed * this.timedelta / 1000; // 每一帧移动的距离
        const dx = this.next_cell.x - this.cells[0].x;
        const dy = this.next_cell.y - this.cells[0].y;
        const distance = Math.sqrt(dx * dx + dy * dy);
        if (distance < this.eps) { // 两点重合, 添加一个新蛇头
            this.cells[0] = this.next_cell; // 走到了目标点，目标点就是新的头
            this.next_cell = null;
            this.status = "idle"; // 走完了，停下来

            if (!this.check_tail_increasing()) { // 若蛇未边长，去掉蛇尾
                this.cells.pop();
            }
            
        } else {
            this.cells[0].x += move_distance * dx / distance;
            this.cells[0].y += move_distance * dy / distance;
        

        if (!this.check_tail_increasing()) {
            const k = this.cells.length;
            const tail = this.cells[k - 1], tail_target = this.cells[k - 2];
            const tail_dx = tail_target.x - tail.x;
            const tail_dy = tail_target.y - tail.y;
            tail.x += move_distance * tail_dx / distance;
            tail.y += move_distance * tail_dy / distance;
        }
    }
}

    check_tail_increasing() { // 检测当前回合蛇长度是否增加
        if (this.step < 10) return true;
        if (this.step % 3 === 1) return true;
        return false;
    }

    update() {
        if (this.status === 'move') {
            this.update_move();
        }
        
        this.render();
    }

    render() {
        const L = this.gamemap.L;
        const ctx = this.gamemap.ctx;

        ctx.fillStyle = this.color;

        if (this.status === "die") {
            ctx.fillStyle = "white";
        }
        for (let cell of this.cells) {
            ctx.beginPath(); // 画笔开始
            ctx.arc(cell.x * L, cell.y * L, L / 2 * 0.8, 0, Math.PI * 2);
            ctx.fill();
        }

        for (let i = 1; i < this.cells.length; i ++ ) {
            const a = this.cells[i - 1], b = this.cells[i];
            if (Math.abs(a.x - b.x) < this.eps && Math.abs(a.y - b.y) < this.eps) { // 若两条蛇在渲染的最后几帧重合(非常接近)
                continue;
            } else if (Math.abs(a.x - b.x) < this.eps) { // 左右走
                ctx.fillRect((a.x - 0.4) * L, Math.min(a.y, b.y) * L, L * 0.8, Math.abs(a.y - b.y) * L);
            } else { // 上下走
                ctx.fillRect(Math.min(a.x, b.x) * L, (a.y - 0.4) * L, Math.abs(a.x - b.x) * L, L * 0.8);
            }
        }

        // 画蛇的眼睛
        ctx.fillStyle = "black";
        for (let i = 0; i < 2; i ++ ) {
            const eye_x = (this.cells[0].x + this.eye_dx[this.eye_direction][i] * 0.15) * L;
            const eye_y = (this.cells[0].y + this.eye_dy[this.eye_direction][i] * 0.15) * L;
            ctx.beginPath();
            ctx.arc(eye_x, eye_y, L * 0.05, 0, Math.PI * 2)
            ctx.fill();
        }     
    }
}